New function which can be used to implement scrolling in non-window
authorMatthias Clasen <mclasen@redhat.com>
Tue, 21 Jun 2005 04:09:52 +0000 (04:09 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Tue, 21 Jun 2005 04:09:52 +0000 (04:09 +0000)
2005-06-21  Matthias Clasen  <mclasen@redhat.com>

* gdk/gdk.symbols:
* gdk/gdkwindow.h:
* gdk/x11/gdkgeometry-x11.c (gdk_window_move_region): New
function which can be used to implement scrolling in
non-window widgets.  (#135165, Søren Sandmann)

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
docs/reference/ChangeLog
docs/reference/gdk/gdk-sections.txt
gdk/gdk.symbols
gdk/gdkwindow.h
gdk/x11/gdkgeometry-x11.c

index afd1bded1e66a7cfd07bc62dc2a4f153d9feeec3..9b96eb41a3aec8749b5aecd12f200f50081893ec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-06-21  Matthias Clasen  <mclasen@redhat.com>
+
+       * gdk/gdk.symbols: 
+       * gdk/gdkwindow.h: 
+       * gdk/x11/gdkgeometry-x11.c (gdk_window_move_region): New
+       function which can be used to implement scrolling in 
+       non-window widgets.  (#135165, Søren Sandmann)
+
 2005-06-20  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkiconcache.c: Handle MAP_FAILED.  (#308449, Georg
index afd1bded1e66a7cfd07bc62dc2a4f153d9feeec3..9b96eb41a3aec8749b5aecd12f200f50081893ec 100644 (file)
@@ -1,3 +1,11 @@
+2005-06-21  Matthias Clasen  <mclasen@redhat.com>
+
+       * gdk/gdk.symbols: 
+       * gdk/gdkwindow.h: 
+       * gdk/x11/gdkgeometry-x11.c (gdk_window_move_region): New
+       function which can be used to implement scrolling in 
+       non-window widgets.  (#135165, Søren Sandmann)
+
 2005-06-20  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkiconcache.c: Handle MAP_FAILED.  (#308449, Georg
index afd1bded1e66a7cfd07bc62dc2a4f153d9feeec3..9b96eb41a3aec8749b5aecd12f200f50081893ec 100644 (file)
@@ -1,3 +1,11 @@
+2005-06-21  Matthias Clasen  <mclasen@redhat.com>
+
+       * gdk/gdk.symbols: 
+       * gdk/gdkwindow.h: 
+       * gdk/x11/gdkgeometry-x11.c (gdk_window_move_region): New
+       function which can be used to implement scrolling in 
+       non-window widgets.  (#135165, Søren Sandmann)
+
 2005-06-20  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkiconcache.c: Handle MAP_FAILED.  (#308449, Georg
index 2f89903b5d403248f69f69358005d229445b7ae0..5b27becfe57a1b59eb101fa1c480bf6aa2292207 100644 (file)
@@ -1,3 +1,7 @@
+2005-06-21  Matthias Clasen  <mclasen@redhat.com>
+
+       * gdk/gdk-sections.txt: Add gdk_window_move_region
+
 2005-06-20  Matthias Clasen  <mclasen@redhat.com>
 
        * === Released 2.7.0 ===
index 36f64f15fa322c9c3239914a1573368e7a2c670d..6dcde195e9f78d5308399db46fa513431568e509 100644 (file)
@@ -643,6 +643,7 @@ gdk_window_move
 gdk_window_resize
 gdk_window_move_resize
 gdk_window_scroll
+gdk_window_move_region
 gdk_window_reparent
 gdk_window_clear
 gdk_window_clear_area
index 7839ece7c4ef74855a17bbda1c6609315e2bd848..ab1159eae8b86142864cf707ec74cf1b936800ad 100644 (file)
@@ -680,6 +680,7 @@ gdk_window_register_dnd
 #if IN_HEADER(__GDK_WINDOW_H__)
 #if IN_FILE(__GDK_GEOMETRY_X11_C__)
 gdk_window_scroll
+gdk_window_move_region
 #endif
 #endif
 
index 85ac3a537acbb4ea79f56cb235fd9915d89bbcfe..6c99cdc61ad53f75d76bb66f6779d14ab55d91c6 100644 (file)
@@ -331,6 +331,10 @@ void          gdk_window_remove_filter         (GdkWindow     *window,
 void          gdk_window_scroll                (GdkWindow *window,
                                                 gint       dx,
                                                 gint       dy);
+void         gdk_window_move_region           (GdkWindow *window,
+                                               GdkRegion *region,
+                                               gint       dx,
+                                               gint       dy);
 
 /* 
  * This allows for making shaped (partially transparent) windows
index f0b33c863607b8933c1b82a6b54f8469562e4ee4..4021dddeba1ed2166eb2f8967c92b916d273a3ee 100644 (file)
@@ -155,6 +155,7 @@ struct _GdkWindowQueueItem
   GdkWindowQueueType type;
   union {
     struct {
+      GdkRegion *area;
       gint dx;
       gint dy;
     } translate;
@@ -183,6 +184,7 @@ static void gdk_window_premove            (GdkWindow          *window,
 static void gdk_window_postmove           (GdkWindow          *window,
                                           GdkWindowParentPos *parent_pos);
 static void gdk_window_queue_translation  (GdkWindow          *window,
+                                          GdkRegion          *area,
                                           gint                dx,
                                           gint                dy);
 static void gdk_window_clip_changed       (GdkWindow          *window,
@@ -231,8 +233,8 @@ gdk_window_copy_area_scroll (GdkWindow    *window,
 
       gc = _gdk_drawable_get_scratch_gc (window, TRUE);
       
-      gdk_window_queue_translation (window, dx, dy);
-
+      gdk_window_queue_translation (window, NULL, dx, dy);
+   
       XCopyArea (GDK_WINDOW_XDISPLAY (window),
                 GDK_WINDOW_XID (window),
                 GDK_WINDOW_XID (window),
@@ -327,7 +329,7 @@ gdk_window_guffaw_scroll (GdkWindow    *window,
   _gdk_x11_window_tmp_unset_bg (window, FALSE);;
 
   if (dx > 0 || dy > 0)
-    gdk_window_queue_translation (window, MAX (dx, 0), MAX (dy, 0));
+    gdk_window_queue_translation (window, NULL, MAX (dx, 0), MAX (dy, 0));
        
   gdk_window_set_static_gravities (window, TRUE);
 
@@ -353,7 +355,7 @@ gdk_window_guffaw_scroll (GdkWindow    *window,
               new_position.x - d_xoffset, new_position.y - d_yoffset);
   
   if (dx < 0 || dy < 0)
-    gdk_window_queue_translation (window, MIN (dx, 0), MIN (dy, 0));
+    gdk_window_queue_translation (window, NULL, MIN (dx, 0), MIN (dy, 0));
   
   XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
                     GDK_WINDOW_XID (window),
@@ -461,6 +463,115 @@ gdk_window_scroll (GdkWindow *window,
     gdk_window_guffaw_scroll (window, dx, dy);
 }
 
+/**
+ * gdk_window_move_region:
+ * @window: a #GdkWindow
+ * @region: The #GdkRegion to move
+ * @dx: Amount to move in the X direction
+ * @dy: Amount to move in the Y direction
+ * 
+ * Move the part of @window indicated by @region by @dy pixels in the Y 
+ * direction and @dx pixels in the X direction. The portions of @region 
+ * that not covered by the new position of @region are invalidated.
+ * 
+ * Child windows are not moved.
+ * 
+ * Since: 2.8
+ **/
+void
+gdk_window_move_region (GdkWindow *window,
+                       GdkRegion *region,
+                       gint       dx,
+                       gint       dy)
+{
+  GdkWindowImplX11 *impl;
+  GdkWindowObject *private;
+  GdkRegion *window_clip;
+  GdkRegion *src_region;
+  GdkRegion *brought_in;
+  GdkRegion *dest_region;
+  GdkRegion *moving_invalid_region;
+  GdkRectangle dest_extents;
+  GdkGC *gc;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (region != NULL);
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  private = GDK_WINDOW_OBJECT (window);
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);  
+
+  if (dx == 0 && dy == 0)
+    return;
+
+  window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
+
+  /* compute source regions */
+  src_region = gdk_region_copy (region);
+  brought_in = gdk_region_copy (region);
+  gdk_region_intersect (src_region, window_clip);
+
+  gdk_region_subtract (brought_in, src_region);
+  gdk_region_offset (brought_in, dx, dy);
+
+  /* compute destination regions */
+  dest_region = gdk_region_copy (src_region);
+  gdk_region_offset (dest_region, dx, dy);
+  gdk_region_intersect (dest_region, window_clip);
+  gdk_region_get_clipbox (dest_region, &dest_extents);
+
+  gdk_region_destroy (window_clip);
+
+  /* calculating moving part of current invalid area */
+  moving_invalid_region = NULL;
+  if (private->update_area)
+    {
+      moving_invalid_region = gdk_region_copy (private->update_area);
+      gdk_region_intersect (moving_invalid_region, src_region);
+      gdk_region_offset (moving_invalid_region, dx, dy);
+    }
+  
+  /* invalidate all of the src region */
+  gdk_window_invalidate_region (window, src_region, FALSE);
+
+  /* un-invalidate destination region */
+  if (private->update_area)
+    gdk_region_subtract (private->update_area, dest_region);
+  
+  /* invalidate moving parts of existing update area */
+  if (moving_invalid_region)
+    {
+      gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
+      gdk_region_destroy (moving_invalid_region);
+    }
+
+  /* invalidate area brought in from off-screen */
+  gdk_window_invalidate_region (window, brought_in, FALSE);
+  gdk_region_destroy (brought_in);
+
+  /* Actually do the moving */
+  gdk_window_queue_translation (window, src_region, dx, dy);
+
+  gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+  gdk_gc_set_clip_region (gc, dest_region);
+  
+  XCopyArea (GDK_WINDOW_XDISPLAY (window),
+            GDK_WINDOW_XID (window),
+            GDK_WINDOW_XID (window),
+            GDK_GC_XGC (gc),
+            dest_extents.x - dx, dest_extents.y - dy,
+            dest_extents.width, dest_extents.height,
+            dest_extents.x, dest_extents.y);
+
+  /* Unset clip region of cached GC */
+  gdk_gc_set_clip_region (gc, NULL);
+  
+  gdk_region_destroy (src_region);
+  gdk_region_destroy (dest_region);
+}
+
 void
 _gdk_window_move_resize_child (GdkWindow *window,
                               gint       x,
@@ -520,7 +631,7 @@ _gdk_window_move_resize_child (GdkWindow *window,
       gdk_window_set_static_gravities (window, TRUE);
 
       if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
+       gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
 
       compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
                                     &new_position);
@@ -541,7 +652,7 @@ _gdk_window_move_resize_child (GdkWindow *window,
                   new_position.x + dx, new_position.y + dy);
       
       if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
+       gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
       
       XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
                         GDK_WINDOW_XID (window),
@@ -797,7 +908,7 @@ gdk_window_premove (GdkWindow          *window,
       GdkRectangle new_position;
 
       if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
+       gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
 
       compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
                                     &new_position);
@@ -843,7 +954,7 @@ gdk_window_postmove (GdkWindow          *window,
   if (d_xoffset != 0 || d_yoffset != 0)
     {
       if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
+       gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
        
       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
                         GDK_DRAWABLE_XID (window),
@@ -917,6 +1028,11 @@ queue_item_free (GdkWindowQueueItem *item)
   
   if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
     gdk_region_destroy (item->u.antiexpose.area);
+  else
+    {
+      if (item->u.translate.area)
+       gdk_region_destroy (item->u.translate.area);
+    }
   
   g_free (item);
 }
@@ -990,11 +1106,13 @@ gdk_window_queue (GdkWindow          *window,
 
 static void
 gdk_window_queue_translation (GdkWindow *window,
+                             GdkRegion *area,
                              gint       dx,
                              gint       dy)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
+  item->u.translate.area = area ? gdk_region_copy (area) : NULL;
   item->u.translate.dx = dx;
   item->u.translate.dy = dy;
 
@@ -1024,7 +1142,7 @@ _gdk_window_process_expose (GdkWindow    *window,
   GdkRegion *clip_region;
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-      
+
   if (display_x11->translate_queue)
     {
       GList *tmp_list = display_x11->translate_queue->head;
@@ -1039,9 +1157,25 @@ _gdk_window_process_expose (GdkWindow    *window,
              if (item->window == window)
                {
                  if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
-                   gdk_region_offset (invalidate_region, item->u.translate.dx, item->u.translate.dy);
+                   {
+                     if (item->u.translate.area)
+                       {
+                         GdkRegion *intersection;
+                         
+                         intersection = gdk_region_copy (invalidate_region);
+                         gdk_region_intersect (intersection, item->u.translate.area);
+                         gdk_region_subtract (invalidate_region, intersection);
+                         gdk_region_offset (intersection, item->u.translate.dx, item->u.translate.dy);
+                         gdk_region_union (invalidate_region, intersection);
+                         gdk_region_destroy (intersection);
+                       }
+                     else
+                       gdk_region_offset (invalidate_region, item->u.translate.dx, item->u.translate.dy);
+                   }
                  else          /* anti-expose */
-                   gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
+                   {
+                     gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
+                   }
                }
            }
          else